package vip.xiaonuo.tasks.service;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;
import vip.xiaonuo.facedoor.modular.memberdevice.constant.MemberDeviceConstant;
import vip.xiaonuo.facedoor.modular.visitor.entity.Visitor;
import vip.xiaonuo.facedoor.modular.visitor.service.FacedoorVisitorService;
import vip.xiaonuo.facedoor.modular.visitor.service.VisitorService;
import vip.xiaonuo.facedoor.modular.visitordevice.entity.VisitorDevice;
import vip.xiaonuo.facedoor.modular.visitordevice.service.VisitorDeviceService;
import vip.xiaonuo.facedoor.iservice.IVisitorDealWithService;
import vip.xiaonuo.facedoor.iservice.entity.PersonBaseParam;
import vip.xiaonuo.facedoor.iservice.entity.PersonBaseParamRet;
import vip.xiaonuo.facedoor.rule.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

@Service
@Slf4j
// todo 等待修改
public class VisitorIssuedService {

    @Autowired
    private VisitorDeviceService visitorDeviceService;

    @Autowired
    private DeviceBaseService deviceBaseService;

    @Autowired
    private VisitorService visitorService;

    Map<String, String> deviceType = new HashMap<String, String>() {
        {
            put("1", "人脸门禁机");
            put("7", "8寸人脸门禁机");
            put("10", "宏图设备");
        }
    };


    public void issued(Long deviceId, List<VisitorDevice> visitorDevices) {
        DeviceBase deviceBase = deviceBaseService.getById(deviceId);
        // 远程调用使用
        PersonBaseParamRet baseParam = getPersonBaseParamRet(deviceBase);
        if (visitorDevices.size() > 50) {
            List<List<VisitorDevice>> splitList = ListUtil.splitAvg(visitorDevices, 3);
            CountDownLatch countDownLatch = new CountDownLatch(3);
            for (List<VisitorDevice> memberDeviceList : splitList) {
                new Thread(() -> {
                    try {
                        issued(memberDeviceList, baseParam, deviceBase);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        countDownLatch.countDown();
                    }
                }).start();
            }
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                log.error("当前线程已经被中断！");
            }
        } else {
            issued(visitorDevices, baseParam, deviceBase);
        }
    }

    private void issued(List<VisitorDevice> visitorDevices, PersonBaseParamRet baseParam, DeviceBase deviceBase) {
        for (VisitorDevice visitorDevice : visitorDevices) {

            // 基础检查
            if (!deviceType.containsKey(deviceBase.getDeviceType())) {
                return;
            }
            Visitor visitor = visitorService.getById(visitorDevice.getVisitorId());
            if (visitor == null) {
                visitorDeviceService.removeById(visitorDevice.getId());
                continue;
            }

            // 先查询人员
            switch (visitorDevice.getStatus()) {
                case MemberDeviceConstant.ADD:
                    if (check(deviceBase, visitorDevice, MemberDeviceConstant.ADD_FAIL, visitor)) {
                        continue;
                    }
                    // 已经过期的 需要在设备中删除
                    if (ObjectUtil.equal(visitor.getStatus(), "0")) {
                        log.error("已经过期执行删除!");
                        visitorDevice.setFailReason("已经过期执行删除！");
                        visitorDevice.setStatus(MemberDeviceConstant.DELETE);
                        visitorDeviceService.updateById(visitorDevice);
                        continue;
                    }
                    // 已经过期的 需要在设备中删除
                    if (!ObjectUtil.equal(visitor.getStatus(), "1")) {
                        log.error("访客不在审批通过状态不进行下发!");
                        visitorDevice.setFailReason("访客不在审批通过状态不进行下发");
                        visitorDevice.setStatus(MemberDeviceConstant.DELETE);
                        visitorDeviceService.updateById(visitorDevice);
                        continue;
                    }
                    log.info("开始下发访客【{}】【{}】", visitor.getName(), visitor.getId());

                    add(visitorDevice, visitor, baseParam);
                    break;
                case MemberDeviceConstant.DELETE:
                    if (check(deviceBase, visitorDevice, MemberDeviceConstant.DELETE_FAIL, visitor)) {
                        continue;
                    }
                    log.info("开始删除访客【{}】【{}】", visitor.getName(), visitor.getId());
                    delete(visitorDevice, visitor, baseParam);
                    break;
                case MemberDeviceConstant.UPDATE:
                    if (check(deviceBase, visitorDevice, MemberDeviceConstant.UPDATE_FAIL, visitor)) {
                        continue;
                    }
                    // 已经过期的 需要在设备中删除
                    if (ObjectUtil.equal(visitor.getStatus(), "0")) {
                        log.error("已经过期执行删除!");
                        visitorDevice.setFailReason("已经过期执行删除！");
                        visitorDevice.setStatus(MemberDeviceConstant.DELETE);
                        visitorDeviceService.updateById(visitorDevice);
                        continue;
                    }
                    if (!ObjectUtil.equal(visitor.getStatus(), "1")) {
                        log.error("访客不在审批通过状态不进行下发!");
                        visitorDevice.setFailReason("访客不在审批通过状态不进行下发");
                        visitorDevice.setStatus(MemberDeviceConstant.UPDATE_FAIL);
                        visitorDeviceService.updateById(visitorDevice);
                        continue;
                    }
                    log.info("开始修改访客【{}】【{}】", visitor.getName(), visitor.getId());
                    update(visitorDevice, visitor, baseParam);
                    break;
            }
        }
    }

    private boolean check(DeviceBase deviceBase, VisitorDevice visitorDevice, int updateFail, Visitor visitor) {
        if (StringUtils.isBlank(deviceBase.getDeviceState()) || deviceBase.getDeviceState().equals("2")) {
            log.error("设备【{}】已经断线 无法进行人员下发", deviceBase.getName());
            visitorDevice.setFailReason("设备已经断线 无法进行人员下发");
            visitorDevice.setStatus(updateFail);
            visitorDeviceService.updateById(visitorDevice);
            return true;
        }
        return false;
    }


    private static PersonBaseParamRet getPersonBaseParamRet(DeviceBase deviceBase) {
        return DeviceTypeRuleService.getIVisitorDealWithService(deviceBase.getDeviceType()).getBaseParam(new PersonBaseParam().setDeviceBase(deviceBase));
    }

    private void update(VisitorDevice visitorDevice, Visitor visitor, PersonBaseParamRet baseParam) {
        DeviceBase deviceBase = deviceBaseService.getById(visitorDevice.getDeviceId());
        try {
            DeviceTypeRuleService.getIVisitorDealWithService(deviceBase.getDeviceType()).update(visitorDevice, visitor, baseParam, deviceBase);
        } catch (Exception e) {
            DeviceTypeRuleService.getIVisitorDealWithService(deviceBase.getDeviceType()).updateException(visitorDevice, visitor, deviceBase, e);
        }
    }


    private void delete(VisitorDevice visitorDevice, Visitor visitor, PersonBaseParamRet baseParam) {
        DeviceBase deviceBase = deviceBaseService.getById(visitorDevice.getDeviceId());
        try {
            DeviceTypeRuleService.getIVisitorDealWithService(deviceBase.getDeviceType()).delete(visitorDevice, visitor, baseParam, deviceBase);
        } catch (Exception e) {
            DeviceTypeRuleService.getIVisitorDealWithService(deviceBase.getDeviceType()).deleteException(visitorDevice, visitor, deviceBase, e);

        }
    }


    private void add(VisitorDevice visitorDevice, Visitor visitor, PersonBaseParamRet baseParam) {
        DeviceBase deviceBase = deviceBaseService.getById(visitorDevice.getDeviceId());
        try {
            DeviceTypeRuleService.getIVisitorDealWithService(deviceBase.getDeviceType()).add(visitorDevice, visitor, baseParam, deviceBase);
        } catch (Exception e) {
            DeviceTypeRuleService.getIVisitorDealWithService(deviceBase.getDeviceType()).addException(visitorDevice, visitor, deviceBase, e);
        }
    }
}
